/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package luft27.zorcon.ui;

import javax.swing.JFrame;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import luft27.comm.*;
import luft27.propertytree.PropertyChangedListener;
import luft27.propertytree.PropertyNode;
import luft27.propertytree.PropertyTree;
import luft27.propertytree.PropertyValue;
import luft27.zorcon.input.Input;

/**
 *
 * @author amalikov
 */
public class MainFrame extends javax.swing.JFrame {

	/**
	 * Creates new form MainFrame
	 */
	public MainFrame() {
		initComponents();
		initMap();
		fcsLink = null;
		input = null;
		serialStream = null;
		
		restoreWindow();
		
		initListeners();
	}
	
	private void initMap() {
		map = new MapView(wwjPanel);
		map.show();
	}
	
	private void initListeners() {
		PropertyChangedListener listener = new PropertyChangedListener() {
			@Override
			public void actionPerformed(PropertyValue value) {
				java.awt.EventQueue.invokeLater(new Runnable() {
					@Override
					public void run() {
						updateLinkStatus();
					}
				});
			}
		};
		
		PropertyTree.INSTANCE.getNode("/linkstatus/goodcnt").addListener(listener);		
		PropertyTree.INSTANCE.getNode("/linkstatus/errcnt").addListener(listener);		
	}
	
	/**
	 * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        wwjPanel = new javax.swing.JPanel();
        javax.swing.JPanel sidePanel = new javax.swing.JPanel();
        connect = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        linkstatus = new javax.swing.JTextField();
        javax.swing.JMenuBar jMenuBar1 = new javax.swing.JMenuBar();
        javax.swing.JMenu settings = new javax.swing.JMenu();
        javax.swing.JMenuItem connectionSettings = new javax.swing.JMenuItem();
        javax.swing.JMenuItem controlSettings = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("ZorCon");
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(640, 480));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        wwjPanel.setBackground(new java.awt.Color(0, 0, 0));

        javax.swing.GroupLayout wwjPanelLayout = new javax.swing.GroupLayout(wwjPanel);
        wwjPanel.setLayout(wwjPanelLayout);
        wwjPanelLayout.setHorizontalGroup(
            wwjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 191, Short.MAX_VALUE)
        );
        wwjPanelLayout.setVerticalGroup(
            wwjPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 0, Short.MAX_VALUE)
        );

        connect.setText("Connect");
        connect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectActionPerformed(evt);
            }
        });

        javax.swing.tree.DefaultMutableTreeNode treeNode1 = new javax.swing.tree.DefaultMutableTreeNode("root");
        jTree1.setModel(new javax.swing.tree.DefaultTreeModel(treeNode1));
        jScrollPane1.setViewportView(jTree1);

        javax.swing.GroupLayout sidePanelLayout = new javax.swing.GroupLayout(sidePanel);
        sidePanel.setLayout(sidePanelLayout);
        sidePanelLayout.setHorizontalGroup(
            sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(sidePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(connect, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(linkstatus, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
            .addGroup(sidePanelLayout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 252, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        sidePanelLayout.setVerticalGroup(
            sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(sidePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(sidePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(connect)
                    .addComponent(linkstatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE))
        );

        settings.setText("Settings");

        connectionSettings.setText("Connection");
        connectionSettings.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectionSettingsActionPerformed(evt);
            }
        });
        settings.add(connectionSettings);

        controlSettings.setText("Control");
        controlSettings.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                controlSettingsActionPerformed(evt);
            }
        });
        settings.add(controlSettings);

        jMenuBar1.add(settings);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(sidePanel, javax.swing.GroupLayout.PREFERRED_SIZE, 251, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(wwjPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(sidePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(wwjPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

	private void connectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectActionPerformed
		if (fcsLink == null) {
			serialStream = createSerialStream();
			fcsLink = new FCSLink(serialStream);
			new Thread(fcsLink).start();
			input = new Input();
			new Thread(input).start();
			connect.setText("Disconnect");
		} else {
			fcsLink.stop();
			fcsLink = null;
			input.stop();
			input = null;
			serialStream.close();
			connect.setText("Connect");
		}
		
		((DefaultTreeModel)jTree1.getModel()).setRoot(new DefaultMutableTreeNode("root"));
		updateTree(PropertyTree.INSTANCE.getRoot(), (DefaultMutableTreeNode)jTree1.getModel().getRoot());
	}//GEN-LAST:event_connectActionPerformed

	private void connectionSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectionSettingsActionPerformed
		new ConnectionSettingsDialog(new JFrame(), true).setVisible(true);
	}//GEN-LAST:event_connectionSettingsActionPerformed

	private void controlSettingsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_controlSettingsActionPerformed
		new ControlSettingsDialog(new JFrame(), true).setVisible(true);
	}//GEN-LAST:event_controlSettingsActionPerformed

	private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
		PropertyNode s = PropertyTree.INSTANCE.getNode("/settings");
		s.set("/window/posx", new PropertyValue(this.getX()));
		s.set("/window/posy", new PropertyValue(this.getY()));
		s.set("/window/sizex", new PropertyValue(this.getWidth()));
		s.set("/window/sizey", new PropertyValue(this.getHeight()));
		s.set(new PropertyValue(0));
		map.saveViewPosition();
	}//GEN-LAST:event_formWindowClosing

	private void restoreWindow() {
		PropertyNode s = PropertyTree.INSTANCE.getNode("/settings");
		this.setLocation(s.get("/window/posx").asInt(), s.get("/window/posy").asInt());
		this.setSize(s.get("/window/sizex").asInt(), s.get("/window/sizey").asInt());
	}
	
	private SerialStream createSerialStream() {
		PropertyNode link = PropertyTree.INSTANCE.getNode("/settings/link");
		
		switch (link.get().asString()) {
		case "com":
			return new COMStream(
					link.get("/com/port").asString(), 
					link.get("/com/baudrate").asInt(), 
					link.get("/timeout").asInt());
		case "udp":
			return new UDPStream(
					link.get("/udp/self").asString(),
					link.get("/udp/selfport").asInt(),
					link.get("/udp/remote").asString(),
					link.get("/udp/remoteport").asInt(),
					link.get("/timeout").asInt());
		case "tcp":
			return new TCPStream(
					link.get("/tcp/host").asString(),
					link.get("/tcp/port").asInt(),
					link.get("/tcp/handshake").asString(),
					link.get("/tcp/server").asBool(),
					link.get("/timeout").asInt());
			
		default:
			return new NullStream();
		}
	}
	
	private void updateTree(PropertyNode pnode, DefaultMutableTreeNode tnode) {
		PropertyNode[] pchildren = pnode.getChildren();
		int i = 0;
		for (PropertyNode pchild : pchildren) {
			DefaultMutableTreeNode tchild = new DefaultMutableTreeNode(pchild.getName() + " (" + pchild.get().asString() + ")");
			((DefaultTreeModel)jTree1.getModel()).insertNodeInto(tchild, tnode, i);
			updateTree(pchild, tchild);
		}
	}
	
	private void updateLinkStatus() {
		PropertyNode lsn = PropertyTree.INSTANCE.getNode("/linkstatus");
		linkstatus.setText(lsn.get("/goodcnt").asInt() + "/" + lsn.get("/errcnt").asInt());
	}
	
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton connect;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTree jTree1;
    private javax.swing.JTextField linkstatus;
    private javax.swing.JPanel wwjPanel;
    // End of variables declaration//GEN-END:variables

	private MapView map;
	private FCSLink fcsLink;
	private Input input;
	private SerialStream serialStream;
}
